﻿using Microsoft.Extensions.DependencyInjection;
using NLog;
using ScheduleTask;
using System;
using System.Reflection;

namespace Qin.ScheduleTask.Common
{
    public abstract class BaseTask : ITask
    {
        protected virtual ILogger Logger => LogManager.GetCurrentClassLogger();
        public string TaskName { get; set; }
        public int RunPeriodInSecond { get; set; }
        public DateTime? WorkingStartTime { get; set; }
        public DateTime? WorkingEndTime { get; set; }
        public TaskType TaskType { get; set; }
        private IServiceProvider ServiceProvider { get; set; }
        public TimeSpan StartTimeSpan { get; private set; }

        public BaseTask(IServiceProvider serviceProvider,
            TaskType taskType, string taskName, int runPeriodInSecond)
            : this(serviceProvider, taskType, taskName, runPeriodInSecond, null, null)
        {
        }

        public BaseTask(IServiceProvider serviceProvider, TaskType taskType, string taskName, DateTime? workingStartTime = null)
            : this(serviceProvider, taskType, taskName, 0, workingStartTime, null)
        {
        }

        /// <summary>
        /// Only for DayTask
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <param name="taskName"></param>
        /// <param name="startTimeSpan"></param>
        public BaseTask(IServiceProvider serviceProvider, TaskType taskType, string taskName, TimeSpan startTimeSpan)
        {
            if (taskType != TaskType.PerDay)
                throw new ArgumentException("This constructor method only for PerDay task");
            this.ServiceProvider = serviceProvider;
            TaskType = taskType;
            TaskName = taskName;
            this.StartTimeSpan = startTimeSpan;
        }

        public BaseTask(IServiceProvider serviceProvider,
            TaskType taskType, string taskName, int runPeriodInSecond, DateTime? workingStartTime = null, DateTime? workingEndTime = null)
        {
            this.ServiceProvider = serviceProvider;
            TaskType = taskType;
            TaskName = taskName;
            RunPeriodInSecond = runPeriodInSecond;
            this.WorkingStartTime = workingStartTime;
            this.WorkingEndTime = workingEndTime;
        }

        public void RunTask()
        {
            using (var scope = ServiceProvider.CreateScope())
            {
                var currentServiceProvider = scope.ServiceProvider;
                try
                {
                    ExecuteTask(currentServiceProvider);
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
        protected abstract void ExecuteTask(IServiceProvider serviceProvider);

        protected void ExceptionHandler(Action action, string errorDisplayName = "")
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                Logger.Error(ex, errorDisplayName);
            }
        }

        private object GetValue(PropertyInfo pi, string value)
        {
            switch (pi.PropertyType.FullName)
            {
                case "System.Decimal":
                    return Convert.ToDecimal(value);
                case "System.Int32":
                    return Convert.ToInt32(value);
                case "System.String":
                    return value;
                default:
                    throw new Exception($"没有找到合适的类型:{pi.Name}{pi.PropertyType.FullName}");
            }
        }
    }
}
